#!/bin/sh

########################################################################
# This test checks that the custom pre- and post-handlers for the callback
# functions can retrieve the arguments and the return values of the
# callees, where appropriate.
# 
# Usage: 
#   sh test.sh
########################################################################

# Just in case the tools like lsmod are not in their usual location.
export PATH=$PATH:/sbin:/bin:/usr/bin

########################################################################
# A function to check prerequisites: whether the necessary files exist,
# etc.
########################################################################
checkPrereqs()
{
	if test ! -f "${CORE_MODULE}"; then
		printf "The core module is missing: ${CORE_MODULE}\n"
		exit 1
	fi

	if test ! -f "${CHECKER_MODULE}"; then
		printf "The \"checker\" module is missing: ${CHECKER_MODULE}\n"
		exit 1
	fi
	
	if test ! -f "${CB_USER_MODULE}"; then
		printf "The \"callback user\" module is missing: ${CB_USER_MODULE}\n"
		exit 1
	fi
		
	if test ! -f "${TARGET_MODULE}"; then
		printf "The target module is missing: ${TARGET_MODULE}\n"
		exit 1
	fi
}

########################################################################
# Cleanup function
########################################################################
cleanupAll()
{
	cd "${WORK_DIR}"
	
	lsmod | grep "${TARGET_MODULE_NAME}" > /dev/null 2>&1
	if test $? -eq 0; then
		rmmod "${TARGET_MODULE_NAME}"
	fi

	lsmod | grep "${CHECKER_MODULE_NAME}" > /dev/null 2>&1
	if test $? -eq 0; then
		rmmod "${CHECKER_MODULE_NAME}"
	fi

	lsmod | grep "${CB_USER_MODULE_NAME}" > /dev/null 2>&1
	if test $? -eq 0; then
		rmmod "${CB_USER_MODULE_NAME}"
	fi
	
	lsmod | grep "${CORE_MODULE_NAME}" > /dev/null 2>&1
	if test $? -eq 0; then
		rmmod "${CORE_MODULE_NAME}"
	fi
}

########################################################################
# checkParam() - checks if the output parameters of the checker module 
# have the expected values.
# 
# $1 - name of the parameter;
# $2 - the expected value of this parameter.
########################################################################
checkParam()
{
	param_file="/sys/module/${CHECKER_MODULE_NAME}/parameters/$1"
	if test ! -e "${param_file}"; then
		printf "Parameter file does not exist: ${param_file}\n"
		cleanupAll
		exit 1
	fi
	
	actual_value=$(cat "${param_file}")
	if test "t${actual_value}" != "t$2"; then
		printf "$1 is \"${actual_value}\" but should be \"$2\"\n"
        cleanupAll
        exit 1 
	fi
}

########################################################################
# doTest() - perform the actual testing
########################################################################
doTest()
{
	insmod "${CORE_MODULE}" \
		targets="${TARGET_MODULE_NAME}" || exit 1

	insmod "${CB_USER_MODULE}"
	if test $? -ne 0; then
		printf "Failed to load the \"callback user\" module: ${CB_USER_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi
	
	insmod "${CHECKER_MODULE}"
	if test $? -ne 0; then
		printf "Failed to load the \"checker\" module: ${CHECKER_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi

	insmod "${TARGET_MODULE}"
	if test $? -ne 0; then
		printf "Failed to load the target module: ${TARGET_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi

	mount -t debugfs none "${TEST_DEBUGFS_DIR}"
	if test $? -ne 0; then
		printf "Failed to mount debugfs to ${TEST_DEBUGFS_DIR}\n"
		cleanupAll
		exit 1
	fi 
	
	# Make the checker module do the test
	echo 1 > "${TEST_DEBUGFS_FILE}"
	if test $? -ne 0; then
		printf "Failed to trigger the test.\n"
		umount "${TEST_DEBUGFS_DIR}"
    	cleanupAll
    	exit 1
	fi
	
	umount "${TEST_DEBUGFS_DIR}"
	
	# Unload the target.
	rmmod "${TARGET_MODULE_NAME}"
	if test $? -ne 0; then
		printf "Failed to unload the target module: ${TARGET_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi

	# Check the results
	checkParam "first_pre_ok" "${EXPECTED_FIRST_PRE}"
	checkParam "first_post_ok" "${EXPECTED_FIRST_POST}"
	checkParam "second_pre_ok" "${EXPECTED_SECOND_PRE}"
	checkParam "second_post_ok" "${EXPECTED_SECOND_POST}"
	
	# Unload the remaining modules, they are no longer needed
	rmmod "${CHECKER_MODULE_NAME}"
	if test $? -ne 0; then
		printf "Failed to unload the module: ${CHECKER_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi
	
	rmmod "${CB_USER_MODULE_NAME}"
	if test $? -ne 0; then
		printf "Failed to unload the module: ${CB_USER_MODULE_NAME}\n"
		cleanupAll
		exit 1
	fi

	rmmod "${CORE_MODULE_NAME}" || exit 1
}
########################################################################
# main
########################################################################
WORK_DIR=${PWD}

EXPECTED_FIRST_PRE=1
EXPECTED_FIRST_POST=1
EXPECTED_SECOND_PRE=1
EXPECTED_SECOND_POST=1

USAGE_STRING="Usage: sh $0"

if test $# -ne 0; then
	printf "${USAGE_STRING}\n"
	exit 1
fi

CORE_MODULE_NAME="@CORE_MODULE_NAME@"
CORE_MODULE="@CORE_MODULE_DIR@/${CORE_MODULE_NAME}.ko"

CB_USER_MODULE_NAME="@TEST_CB_USER_NAME@"
CB_USER_MODULE="@TEST_CB_USER_DIR@/${CB_USER_MODULE_NAME}.ko"

CHECKER_MODULE_NAME="@TEST_CHECKER_NAME@"
CHECKER_MODULE="@TEST_CHECKER_DIR@/${CHECKER_MODULE_NAME}.ko"

TARGET_MODULE_NAME="@TEST_TARGET_NAME@"
TARGET_MODULE="@TEST_TARGET_DIR@/${TARGET_MODULE_NAME}.ko"

TEST_TMP_DIR="@KEDR_TEST_TEMP_DIR@"
TEST_DEBUGFS_DIR="${TEST_TMP_DIR}/debug"
TEST_DEBUGFS_FILE="${TEST_DEBUGFS_DIR}/${CB_USER_MODULE_NAME}/do_test"

checkPrereqs

rm -rf "${TEST_TMP_DIR}"
mkdir -p "${TEST_DEBUGFS_DIR}"
if test $? -ne 0; then
	printf "Failed to create ${TEST_DEBUGFS_DIR}\n"
	exit 1
fi 

doTest

# just in case
cleanupAll

# test passed
exit 0
